use std::{rc::Rc, cell::RefCell};

use crate::{instructions::base::{self, Instruction, BytecodeReader}, rtda::Frame};

// 把操作数栈顶的int变量弹出，然后跟0进行比较，满足条件则跳转。

// ifeq:x == 0
// Branch if int comparison with zero succeeds
#[derive(Debug, Default)]
pub struct IFEQ {
    offset: i32
}

impl Instruction for IFEQ {
    fn fetch_operands(&mut self, reader: &mut BytecodeReader) {
        self.offset = reader.read_i16() as i32;
    }

    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let val = frame.borrow().get_operand_stack().borrow_mut().pop_int();
        if val == 0 {
            base::branch(frame, self.offset)
        }
    }
}

// ifne:x ! = 0
#[derive(Debug, Default)]
pub struct IFNE {
    offset: i32
}

impl Instruction for IFNE {
    fn fetch_operands(&mut self, reader: &mut BytecodeReader) {
        self.offset = reader.read_i16() as i32;
    }

    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let val = frame.borrow().get_operand_stack().borrow_mut().pop_int();
        if val != 0 {
            base::branch(frame, self.offset)
        }
    }
}

// iflt:x < 0
#[derive(Debug, Default)]
pub struct IFLT {
    offset: i32
}

impl Instruction for IFLT {
    fn fetch_operands(&mut self, reader: &mut BytecodeReader) {
        self.offset = reader.read_i16() as i32;
    }

    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let val = frame.borrow().get_operand_stack().borrow_mut().pop_int();
        if val < 0 {
            base::branch(frame, self.offset)
        }
    }
}

// ifle:x <= 0
#[derive(Debug, Default)]
pub struct IFLE {
    offset: i32
}

impl Instruction for IFLE {
    fn fetch_operands(&mut self, reader: &mut BytecodeReader) {
        self.offset = reader.read_i16() as i32;
    }

    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let val = frame.borrow().get_operand_stack().borrow_mut().pop_int();
        if val <= 0 {
            base::branch(frame, self.offset)
        }
    }
}

// ifgt:x > 0
#[derive(Debug, Default)]
pub struct IFGT {
    offset: i32
}

impl Instruction for IFGT {
    fn fetch_operands(&mut self, reader: &mut BytecodeReader) {
        self.offset = reader.read_i16() as i32;
    }

    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let val = frame.borrow().get_operand_stack().borrow_mut().pop_int();
        if val > 0 {
            base::branch(frame, self.offset)
        }
    }
}

// ifgt:x >= 0
#[derive(Debug, Default)]
pub struct IFGE {
    offset: i32
}

impl Instruction for IFGE {
    fn fetch_operands(&mut self, reader: &mut BytecodeReader) {
        self.offset = reader.read_i16() as i32;
    }

    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let val = frame.borrow().get_operand_stack().borrow_mut().pop_int();
        if val >= 0 {
            base::branch(frame, self.offset)
        }
    }
}